package nl.hva.three2learn.controller;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpSession;

import nl.hva.three2learn.authentication.AdminAuthority;
import nl.hva.three2learn.authentication.Role;
import nl.hva.three2learn.authentication.TeacherAuthority;
import nl.hva.three2learn.authentication.UserAuthentication;
import nl.hva.three2learn.authentication.UserAuthenticationDetails;
import nl.hva.three2learn.authentication.UserAuthority;
import nl.hva.three2learn.dao.UserDao;
import nl.hva.three2learn.model.User;
import nl.hva.three2learn.util.Password;
import nl.hva.three2learn.util.Validate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.context.MessageSource;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Handles requests for the application home page.
 */
@Controller
public class UserController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private JavaMailSenderImpl mailSender;
	
	@Autowired
	private MessageSource messageSource;
	
	@RequestMapping(value = "/register_user", method = RequestMethod.GET)
	public String registerUser(Locale locale, Model model, HttpSession session) {
		
		logger.info("Debug: register_user "+ locale.toString());
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "register_user";
	}
	
	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public String searchUserAll(HttpSession session,
			UserAuthentication userAuthentication)
	{
			//if(userAuthentication.getUser())
		session.setAttribute("listUsers", userDao.findAllUsers());
		return "list_users";
	}
	
	@RequestMapping(value = "/start_modify_user", method = RequestMethod.GET)
	public String startModifyUser(HttpSession session,
			@RequestParam("userId") long userId,
			UserAuthentication userAuthentication)
	{
		session.setAttribute("user", userDao.findById(userId));
		return "modify_user";
	}
	
	@RequestMapping(value = "/start_modify_current_user", method = RequestMethod.GET)
	public String startModifyCurrentUser(HttpSession session,
			UserAuthentication userAuthentication)
	{
		session.setAttribute("user", userAuthentication.getUser());
		return "modify_current_user";
	}
	
	@RequestMapping(value = "/modify_current_user", method = RequestMethod.POST)
	public String modifyCurrentUser(UserAuthentication userAuthentication,
			@RequestParam("first_name")   String firstName,
			@RequestParam("last_name")    String lastName,
			@RequestParam("email")        String email,
			@RequestParam("password")     String password,
			@RequestParam("country")      String country,
			@RequestParam("city")         String city,
			@RequestParam("street")       String street,
			@RequestParam("postal")       String postal,
			@RequestParam("phone_number") String phoneNumber,
			@RequestParam("house_number") int houseNumber)
	{
		User user = userAuthentication.getUser();
		
		
		user.setFirstName(firstName);
		user.setLastName(lastName);
		user.setCountry(country);
		user.setCity(city);
		user.setStreet(street);
		user.setPostal(postal);
		user.setHouseNumber(houseNumber);
		user.setPhoneNumber(phoneNumber);
		
		
		userDao.save(user);
		
		SecurityContext context = SecurityContextHolder.getContext();
		context.setAuthentication(
				new UserAuthentication(
						new UserAuthenticationDetails(user, new GrantedAuthority[] { new UserAuthority() })
					)
				);
		
		return "redirect:/";
	}
	
	@RequestMapping(value = "/modify_user", method = RequestMethod.POST)
	public String modifyUser(
			@RequestParam("first_name")   String firstName,
			@RequestParam("last_name")    String lastName,
			@RequestParam("country")      String country,
			@RequestParam("city")         String city,
			@RequestParam("street")       String street,
			@RequestParam("postal")       String postal,
			@RequestParam("phone_number") String phoneNumber,
			@RequestParam("house_number") int houseNumber,
			
			@RequestParam("userID") long id)
	{
		User user = userDao.findById(id);
		
		
		user.setFirstName(firstName);
		user.setLastName(lastName);
		user.setCountry(country);
		user.setCity(city);
		user.setStreet(street);
		user.setPostal(postal);
		user.setHouseNumber(houseNumber);
		user.setPhoneNumber(phoneNumber);
		
		
		userDao.save(user);
		
		return "redirect:/";
	}
	
	@RequestMapping(value = "/add_user", method = RequestMethod.POST)
	public String addUser(
			@RequestParam("first_name")   String firstName,
			@RequestParam("last_name")    String lastName,
			@RequestParam("email")        String email,
			@RequestParam("password")     String password,
			@RequestParam("country")      String country,
			@RequestParam("city")         String city,
			@RequestParam("street")       String street,
			@RequestParam("postal")       String postal,
			@RequestParam("phone_number") String phoneNumber,
			@RequestParam("house_number") int houseNumber,
			
			@RequestParam("subject")   String subject,
			@RequestParam("greetings") String greetings,
			@RequestParam("content")   String content,
			@RequestParam("footer")    String footer) {
		//logger.info("Debug: add_user "+ locale.toString());
		

		User newUser = new User();
////////////////////
//Get attributes		
		
		logger.info("Debug: firstName "+ firstName);
		logger.info("Debug: lastName "+ lastName);
		logger.info("Debug: email "+ email);
		logger.info("Debug: password "+ password);
		logger.info("Debug: country "+ country);
		logger.info("Debug: city "+ city);
		logger.info("Debug: street "+ street);
		logger.info("Debug: phoneNumber "+ phoneNumber);
		logger.info("Debug: postal "+ postal);
		logger.info("Debug: houseNumber "+ houseNumber);
		
		
////////////////////
		
///////////////////
//Set attributes
		newUser.setFirstName(firstName);
		newUser.setLastName(lastName);
		newUser.setEmail(email);
		newUser.setPassword(Password.genHash(password, email));
		newUser.setCountry(country);
		newUser.setCity(city);
		newUser.setStreet(street);
		newUser.setPostal(postal);
		newUser.setPhoneNumber(phoneNumber);
		newUser.setHouseNumber(houseNumber);
///////////////////		
		
		newUser.setActive(false);
		newUser.setDisabled(false);

		//Save user
		userDao.save(newUser);
		
		MimeMessage msg = mailSender.createMimeMessage();
		
		
		try {
			MimeMessageHelper helper = new MimeMessageHelper(msg, true);
			
			helper.setTo(email);
			helper.setSubject(subject);
		//SimpleMailMessage msg = new SimpleMailMessage();
		//msg.setTo(email);
			helper.setText(
				"<html><body>" +
				"<p>" + greetings + " " + newUser.getLastName() + ", " + newUser.getFirstName() + "</p>" +
				"<p>" + content + "</p>" +
				"<p>" + footer + "</p>" +
				"</body></html>",
				true);
		} catch(MessagingException e) {
			logger.debug(e.getMessage());
		}
		
		mailSender.send(msg);
		
		return "redirect:/";
	}
	
	/*
	 * Attempt to log in to the system.
	 */
	@RequestMapping(value = "/activate_user", method = RequestMethod.POST)
	public String activateUser(HttpSession session, Locale locale,
			@RequestParam("email")    String email,
			@RequestParam("password") String password) {
		
		User user = userDao.findByEmail(email);

		// User doesn't exist or the login credentials were invalid
		if (user == null || !Validate.user(user, Password.genHash(password, email))) {
			session.setAttribute("loginError", messageSource.getMessage("login.error.credentials", null, locale));
			return "redirect:/";
		}
		
		// Everything went well - attach the user to the session and
		// set the user' state to active
		
		user.setActive(true);
		userDao.save(user);
		
		GrantedAuthority[] authorities = null;
		
		String redirectUrl = "/";
		
		// Assign the right authorities to the user with
		// the right role
		switch (user.getRole()) {
			case ADMIN:
				authorities = new GrantedAuthority[] {
						new AdminAuthority()
				};
				redirectUrl = "/admin/";
				break;
				
			case TEACHER:
				authorities = new GrantedAuthority[] {
						new UserAuthority(),
						new TeacherAuthority()
				};
				break;
				
			case USER:
				authorities = new GrantedAuthority[] {
						new UserAuthority()
				};
				break;
		}
		
		// Log the user in O_o
		SecurityContext context = SecurityContextHolder.getContext();
		context.setAuthentication(
				new UserAuthentication(
						new UserAuthenticationDetails(user, authorities)
					)
				);
		
		return "redirect:" + redirectUrl;
	}
	
	/*
	 * Attempt to log out of the system.
	 */
	@RequestMapping(value = "/deactivate_user", method = RequestMethod.POST)
	public String deactivateUser(UserAuthentication auth) {
		
		// Not logged in
		if (auth == null)
			return "redirect:/";
		
		User user = userDao.findById(auth.getUser().getId());
		
		user.setActive(false);
		userDao.save(user);
		
		// Log the user out by setting the authentication object to null
		SecurityContextHolder.getContext().setAuthentication(null);
		
		return "redirect:/";
	}
	
	/*
	 * reset password and send the new password to email.
	 */
	@RequestMapping(value = "/reset_password", method = RequestMethod.POST)
	public String resetPassword(
			@RequestParam("email")	   String email,
			@RequestParam("subject")   String subject,
			@RequestParam("greetings") String greetings,
			@RequestParam("content")   String content,
			@RequestParam("footer")    String footer) {
		
		User user = userDao.findByEmail(email);
		
		String password = Password.generateString(
				"abcdefghijklmnopqrstuvwxyz" +
				"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
				"0123456789_", 14);
		
		user.setPassword(Password.genHash(password, email));
		userDao.save(user);
		
		MimeMessage msg = mailSender.createMimeMessage();
		
		
		try {
			MimeMessageHelper helper = new MimeMessageHelper(msg, true);
			
			helper.setTo(email);
			helper.setSubject(subject);
		//SimpleMailMessage msg = new SimpleMailMessage();
		//msg.setTo(email);
			helper.setText(
				"<html><body>" +
				"<p>" + greetings + " " + user.getLastName() + ", " + user.getFirstName() + "</p>" +
				"<p>" + content + " " + password + "</p>" +
				"<p>" + footer + "</p>" +
				"</body></html>",
				true);
		} catch(MessagingException e) {
			logger.debug(e.getMessage());
		}
		
		mailSender.send(msg);
		return "redirect:/";
	}
	
	/*
	 * Disable a student
	 */
	@RequestMapping(value = "/disable_user", method = RequestMethod.POST)
	public String disableUser(@RequestParam("user") long userId) {
		
		User user = userDao.findById(userId);
		user.setDisabled(true);
		
		userDao.save(user);
		return "redirect:/";
	}
}
